from django.conf import settings
from django.forms.models import model_to_dict
from rest_framework import serializers
from rest_framework.exceptions import PermissionDenied

from prj005.models import (
    clinical, cure, history, info,
    relevant, result, summary
)
from utils.samecode import ExtendsSerializer
from utils.savemobile import create_object
from utils.constants import permission_deny_message

from celery_tasks import tasks


class SCSerializer(serializers.HyperlinkedModelSerializer):
    create_time = serializers.DateTimeField(format=settings.DATETIME_FORMAT, read_only=True)

    def validate_info(self, value):
        owner = value.owner
        user = self.context['view'].request.user

        if owner != user:
            raise PermissionDenied(detail=permission_deny_message.get('exist_info'))
        return value

    def update(self, instance, validated_data):
        current_info = validated_data.get('info')
        if current_info and current_info != instance.info:
            raise PermissionDenied(detail=permission_deny_message.get('exist_info'))

        # 更新的字段
        try:
            prj_name = self.Meta.project_name
            serial = instance.info.serial
            if instance.info.check_status == '审核不通过':
                before_instance = model_to_dict(instance)
                try:
                    before_instance.pop('info')
                    before_instance.pop('owner')
                    validated_data.pop('info')
                except KeyError:
                    tasks.celery_save_data.delay(before_instance, validated_data, serial, project_name=prj_name)
                else:
                    tasks.celery_save_data.delay(before_instance, validated_data, serial, project_name=prj_name)
        except Exception:
            raise ValueError('记录更新字段错误')

        return super().update(instance, validated_data)


class SearchSerializer(serializers.ModelSerializer):
    """ For search api """
    patient_birth = serializers.CharField(required=False, help_text='出生年份')
    patient_career = serializers.CharField(required=False, help_text='职业')
    patient_name = serializers.CharField(required=False, help_text='姓名')
    patient_phone = serializers.CharField(required=False, help_text='手机号')
    hospital_name = serializers.CharField(required=False, help_text='所在医院')
    # address = serializers.CharField(required=False, help_text='地址')
    check_status = serializers.CharField(required=False, help_text='审核状态')

    # 针对用户进行查询
    owner__user_name = serializers.CharField(help_text='医生姓名', required=False)
    owner__hospital = serializers.CharField(help_text='医生所在医院', required=False)

    class Meta:
        model = info.Info
        fields = [
            'patient_name', 'patient_phone', 'hospital_name',
            'patient_birth', 'patient_career', 'check_status',
            'owner__user_name', 'owner__hospital'
        ]


class ClinicalLinkSerializer(SCSerializer):

    class Meta:
        model = clinical.Clinical
        fields = '__all__'
        project_name = 'prj005'
        read_only_fields = ['owner', ]
        extra_kwargs = {
            'url': {
                'view_name': 'prj005-clinical-detail',
                'lookup_field': 'pk'
            },
            'info': {
                'view_name': 'prj005-info-detail',
            }
        }


class CureLinkSerializer(SCSerializer):

    class Meta:
        model = cure.Cure
        fields = '__all__'
        project_name = 'prj005'
        read_only_fields = ['owner', ]
        extra_kwargs = {
            'url': {
                'view_name': 'prj005-cure-detail',
                'lookup_field': 'pk'
            },
            'info': {
                'view_name': 'prj005-info-detail',
            }
        }


class HistoryLinkSerializer(SCSerializer):

    class Meta:
        model = history.History
        fields = '__all__'
        project_name = 'prj005'
        read_only_fields = ['owner', ]
        extra_kwargs = {
            'url': {
                'view_name': 'prj005-history-detail',
                'lookup_field': 'pk'
            },
            'info': {
                'view_name': 'prj005-info-detail',
            }
        }


class InfoLinkSerializer(ExtendsSerializer, serializers.HyperlinkedModelSerializer):
    check = serializers.HyperlinkedIdentityField(read_only=True, view_name='prj005-info-check', lookup_field='pk',)
    summary = serializers.HyperlinkedRelatedField(read_only=True, view_name='prj005-summary-detail')
    history = serializers.HyperlinkedRelatedField(read_only=True, view_name='prj005-history-detail')
    relevant = serializers.HyperlinkedRelatedField(read_only=True, view_name='prj005-relevant-detail')
    clinical = serializers.HyperlinkedRelatedField(read_only=True, view_name='prj005-clinical-detail')
    cure = serializers.HyperlinkedRelatedField(read_only=True, view_name='prj005-cure-detail')
    result = serializers.HyperlinkedRelatedField(read_only=True, view_name='prj005-result-detail')
    info = serializers.HyperlinkedIdentityField(read_only=True, view_name='prj005-info-detail', lookup_field='pk')
    owner_id = serializers.PrimaryKeyRelatedField(label='辅助医生ID', read_only=True)
    owner_name = serializers.StringRelatedField(label='辅助医生姓名', read_only=True, source='owner.user_name')
    create_time = serializers.DateTimeField(format=settings.DATETIME_FORMAT, read_only=True)

    class Meta:
        model = info.Info
        fields = '__all__'
        project_name = 'prj005'
        save_mobile = False
        read_only_fields = ['owner', 'serial', 'create_time', 'check_status', 'reason_for_check']
        extra_kwargs = {
            'url': {
                'view_name': 'prj005-info-detail',
                'lookup_field': 'pk'
            }
        }


class RelevantLinkSerializer(SCSerializer):

    class Meta:
        model = relevant.Relevant
        fields = '__all__'
        project_name = 'prj005'
        read_only_fields = ['owner', ]
        extra_kwargs = {
            'url': {
                'view_name': 'prj005-relevant-detail',
                'lookup_field': 'pk'
            },
            'info': {
                'view_name': 'prj005-info-detail',
            }
        }


class ResultLinkSerializer(SCSerializer):

    class Meta:
        model = result.Result
        fields = '__all__'
        project_name = 'prj005'
        read_only_fields = ['owner', ]
        extra_kwargs = {
            'url': {
                'view_name': 'prj005-result-detail',
                'lookup_field': 'pk'
            },
            'info': {
                'view_name': 'prj005-info-detail',
            }
        }


class SummaryLinkSerializer(SCSerializer):

    class Meta:
        model = summary.Summary
        fields = '__all__'
        project_name = 'prj005'
        read_only_fields = ['owner', ]
        extra_kwargs = {
            'url': {
                'view_name': 'prj005-summary-detail',
                'lookup_field': 'pk'
            },
            'info': {
                'view_name': 'prj005-info-detail',
            }
        }


class InfoSerializer(ExtendsSerializer, serializers.ModelSerializer):

    class Meta:
        model = info.Info
        exclude = ['create_time', 'id']
        read_only_fields = ['serial', 'check_status', 'reason_for_check']
        project_name = 'prj004'
        save_mobile = True


class ClinicalSerializer(serializers.ModelSerializer):

    class Meta:
        model = clinical.Clinical
        exclude = ['owner', 'create_time', 'info', 'id']


class CureSerializer(serializers.ModelSerializer):

    class Meta:
        model = cure.Cure
        exclude = ['owner', 'create_time', 'info', 'id']


class HistorySerializer(serializers.ModelSerializer):

    class Meta:
        model = history.History
        exclude = ['owner', 'create_time', 'info', 'id']


class RelevantSerializer(serializers.ModelSerializer):

    class Meta:
        model = relevant.Relevant
        exclude = ['owner', 'create_time', 'info', 'id']


class ResultSerializer(serializers.ModelSerializer):

    class Meta:
        model = result.Result
        exclude = ['owner', 'create_time', 'info', 'id']


class SummarySerializer(serializers.ModelSerializer):

    class Meta:
        model = summary.Summary
        exclude = ['owner', 'create_time', 'info', 'id']


class AllSerializer(serializers.Serializer):
    info = InfoSerializer(required=False)
    history = HistorySerializer(required=False)
    clinical = ClinicalSerializer(required=False)
    cure = CureSerializer(required=False)
    summary = SummarySerializer(required=False)
    result = ResultSerializer(required=False)
    relevant = RelevantSerializer(required=False)


class CheckStatusSerializer(serializers.Serializer):
    CHECKED_STATUS = [i[0] for i in info.Info.CHECKED_CHOICE]
    CHECKED_CHOICE = info.Info.CHECKED_CHOICE

    check_status = serializers.ChoiceField(required=True, choices=CHECKED_CHOICE, help_text='审核状态')
    reason_for_check = serializers.CharField(required=False, help_text='审核不通过原因')

    def validate(self, value):
        status = value.get('check_status')
        if status not in self.CHECKED_STATUS:
            raise serializers.ValidationError('非法审核状态')

        reason = value.get('reason_for_check')

        if status == '审核不通过' and not reason:
            raise serializers.ValidationError('审核不通过的原因未填写.')

        return value


class MobileSerializer(serializers.Serializer):
    info = InfoSerializer(required=True)
    clinical = ClinicalSerializer(required=False)
    cure = CureSerializer(required=False)
    history = HistorySerializer(required=False)
    summary = SummarySerializer(required=False)
    relevant = RelevantSerializer(required=False)
    result = ResultSerializer(required=False)

    def create(self, instance):
        info = instance.get('info')
        info_owner = info.pop('owner')
        info['owner'] = info_owner.id

        info_serializer = InfoSerializer(data=info)
        info_serializer.is_valid(raise_exception=True)
        info_instance = info_serializer.save()

        summary = instance.get('summary')
        history = instance.get('history')
        cure = instance.get('cure')
        clinical = instance.get('clinical')
        relevant = instance.get('relevant')
        result = instance.get('result')

        create_object(info_instance, summary, SummarySerializer)
        create_object(info_instance, history, HistorySerializer)
        create_object(info_instance, cure, CureSerializer)
        create_object(info_instance, clinical, ClinicalSerializer)
        create_object(info_instance, result, ResultSerializer)
        create_object(info_instance, relevant, RelevantSerializer)

        return instance
